home *** CD-ROM | disk | FTP | other *** search
/ Software 2000 / Software 2000 Volume 1 (Disc 1 of 2).iso / education / e078.dms / e078.adf / BEZIER / source / ORIG / BEZIER.C
C/C++ Source or Header  |  1988-10-05  |  6KB  |  281 lines

  1.  
  2. /*
  3.  *  BEZIER.C
  4.  *
  5.  *  Matthew Dillon.
  6.  *  Public Domain (no Copyrights whatsoever)
  7.  *
  8.  *  -Assumes AZTEC compilation,  +L (32 bit ints), with all AMIGA symbols
  9.  *  precompiled.  Additionally expects certain typedefs and routines
  10.  *  found in MY.LIB, as well as some MY.LIB #include files.
  11.  *
  12.  *  An experienced programmer can remove the MY.LIB dependancies
  13.  *  (openlibs() call), and figure out what typedefs have been assumed if
  14.  *  he wishes to compile the program.  You can also simply extract the
  15.  *  Bezier functions for your own use.
  16.  */
  17.  
  18. #include <typedefs.h>
  19. #include <xmisc.h>
  20.  
  21. #define     SHIFTS  9
  22. #define     ONE     (1<<SHIFTS)
  23.  
  24. typedef struct PropInfo XPI;
  25. typedef struct Image    IM;
  26.  
  27. extern IMESS *GetMsg();
  28.  
  29. #define MYGADGETS   (WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE)
  30.  
  31. NW Nw = {
  32.     64, 64, 320, 100,
  33.     0, 1,
  34.     NEWSIZE|MOUSEBUTTONS|MOUSEMOVE|CLOSEWINDOW|GADGETDOWN|GADGETUP,
  35.     MYGADGETS|REPORTMOUSE|ACTIVATE|NOCAREREFRESH,
  36.     0, 0, (UBYTE *)"Bezier", NULL, NULL,
  37.     32, 64, -1, -1, WBENCHSCREEN
  38. };
  39.  
  40. WIN *Win;
  41. RP  *Rp;
  42. short Ux, Uy, Lx, Ly;
  43. short Step = 128;
  44.  
  45. main(ac, av)
  46. char *av[];
  47. {
  48.     register IMESS *mess;
  49.     short notdone = 1;
  50.     short pt = -1;
  51.     short ptarray[4][2];
  52.  
  53.     short gy, gg = 0;
  54.     XPI *po;
  55.  
  56.     init_gadgets(&Nw, &po);
  57.     exiterr(!openlibs(INTUITION_LIB|GRAPHICS_LIB), "unable to open libs");
  58.     exiterr(!(Win = OpenWindow(&Nw)), "unable to open window");
  59.     Rp = Win->RPort;
  60.     SetAPen(Rp, 1);
  61.     setpoint(ptarray, 0, 32, 32);
  62.     setpoint(ptarray, 1, 40, 40);
  63.     setpoint(ptarray, 2, 50, 50);
  64.     setpoint(ptarray, 3, 60, 60);
  65.     setbounds(ptarray);
  66.     while (notdone) {
  67.     short mx, my, mm = 0;
  68.     WaitPort(Win->UserPort);
  69.     while (mess = GetMsg(Win->UserPort)) {
  70.         switch(mess->Class) {
  71.         case CLOSEWINDOW:
  72.         notdone = 0;
  73.         break;
  74.         case NEWSIZE:
  75.         setbounds(ptarray);
  76.         break;
  77.         case GADGETUP:
  78.         case GADGETDOWN:
  79.         {
  80.             gg = mess->Class;
  81.             gy = po->VertPot / 256;
  82.         }
  83.         break;
  84.         case MOUSEBUTTONS:
  85.         switch(mess->Code) {
  86.         case SELECTDOWN:
  87.             pt = getpoint(ptarray, mess->MouseX, mess->MouseY);
  88.             break;
  89.         case SELECTUP:
  90.             pt = -1;
  91.             break;
  92.         }
  93.         break;
  94.         case MOUSEMOVE:
  95.         if (gg == GADGETDOWN) {
  96.             gy = po->VertPot / 256;
  97.             break;
  98.         }
  99.         mm = 1;
  100.         mx = mess->MouseX;
  101.         my = mess->MouseY;
  102.         break;
  103.         default:
  104.         break;
  105.         }
  106.         ReplyMsg(mess);
  107.     }
  108.     if (mm && pt >= 0) {
  109.         movepoint(ptarray, pt, mx, my);
  110.         drawcurve(ptarray);
  111.     }
  112.     if (gg) {
  113.         char buf[32];
  114.         if (gg == GADGETUP)
  115.         gg = 0;
  116.         if (gy + 1 >= 0)
  117.         Step = gy + 1;
  118.         sprintf(buf, "gran: %4ld/%ld", Step, ONE);
  119.         drawcurve(ptarray);
  120.         Move(Rp, Ux + 1, Uy + 16);
  121.         Text(Rp, buf, strlen(buf));
  122.     }
  123.     }
  124.     exiterr(1, NULL);
  125. }
  126.  
  127. exiterr(n, str)
  128. char *str;
  129. {
  130.     if (n) {
  131.     if (str)
  132.         puts(str);
  133.     if (Win)
  134.         CloseWindow(Win);
  135.     closelibs(-1);
  136.     exit(1);
  137.     }
  138. }
  139.  
  140. setbounds(a)
  141. register long *a;
  142. {
  143.     Ux = Win->BorderLeft;
  144.     Uy = Win->BorderTop;
  145.     Lx = Win->Width - Win->BorderRight;
  146.     Ly = Win->Height- Win->BorderBottom;
  147.     drawcurve(a);
  148. }
  149.  
  150. setpoint(a, pt, x, y)
  151. register short a[4][2];
  152. {
  153.     a[pt][0] = x;
  154.     a[pt][1] = y;
  155.     drawpoints(a, pt, pt + 1);
  156. }
  157.  
  158. getpoint(a, x, y)
  159. register short a[4][2];
  160. {
  161.     register short i, bi;
  162.     register long r, br;
  163.  
  164.     for (i = bi = 0, br = 0x7FFFFFFF; i < 4; ++i) {
  165.     r = (x-a[i][0])*(x-a[i][0]) + (y-a[i][1])*(y-a[i][1]);
  166.     if (r < br) {
  167.         bi = i;
  168.         br = r;
  169.     }
  170.     }
  171.     return(bi);
  172. }
  173.  
  174. movepoint(a, pt, x, y)
  175. register short a[4][2];
  176. {
  177.     SetAPen(Rp, 0);
  178.     drawpoints(a, pt, pt + 1);
  179.     SetAPen(Rp, 1);
  180.     setpoint(a, pt, x, y);
  181. }
  182.  
  183. #define S10(x)     ((x) >> SHIFTS)
  184. #define S20(x)     ((x) >> (2*SHIFTS))
  185.  
  186. /*
  187.  *  So I can use integer arithmatic, I am defining 512 as 1 (as far
  188.  *  as the mathematics go), which means that I must divide any power
  189.  *  multiplication by 512^(n-1).  E.G. .5^2 = .25 ... to make 256^2
  190.  *  equal 128, I must divide by 512^1
  191.  */
  192.  
  193. drawcurve(a)
  194. register short a[4][2];
  195. {
  196.     long  m1[4];    /* t matrix            */
  197.     long  mr[4];    /* partial result matrix    */
  198.     long  corr[2];
  199.     register short t, i;
  200.     char  lastpt = 0;
  201.  
  202.     SetAPen(Rp, 0);
  203.     RectFill(Rp, Ux, Uy, Lx - 1, Ly - 1);
  204.     SetAPen(Rp, 1);
  205.     drawpoints(a, 0, 4);
  206.  
  207.     Move(Rp, a[0][0], a[0][1]);
  208.     for (t = 0; t <= ONE; t += Step) {       /*  t = 0 to 1      */
  209. oncemore:
  210.     m1[3] = ONE;
  211.     m1[2] = t;
  212.     m1[1] = t * t;
  213.     m1[0] = m1[1] * t;
  214.  
  215.     mr[0] = -S20(m1[0]  ) + S10(3*m1[1]) - 3*m1[2] + m1[3];
  216.     mr[1] =  S20(3*m1[0]) - S10(6*m1[1]) + 3*m1[2];
  217.     mr[2] = -S20(3*m1[0]) + S10(3*m1[1]);
  218.     mr[3] =  S20(m1[0]  );
  219.     for (i = 0; i < 2; ++i) {
  220.         corr[i] = (mr[0] * a[0][i] + mr[1] * a[1][i] +
  221.               mr[2] * a[2][i] + mr[3] * a[3][i]) >> SHIFTS;
  222.     }
  223.     Draw(Rp, corr[0], corr[1]);
  224.     }
  225.     if (lastpt == 0 && t - Step < ONE) {
  226.     lastpt = 1;
  227.     t = ONE;
  228.     goto oncemore;
  229.     }
  230. }
  231.  
  232. drawpoints(a, is, ie)
  233. register short a[4][2];
  234. {
  235.     register short i;
  236.     for (i = is; i < ie; ++i) {
  237.     Move(Rp, a[i][0] - 2, a[i][1]);
  238.     Draw(Rp, a[i][0] + 2, a[i][1]);
  239.     Move(Rp, a[i][0], a[i][1] - 2);
  240.     Draw(Rp, a[i][0], a[i][1] + 2);
  241.     }
  242. }
  243.  
  244. /*
  245.  *  GADGET ROUTINES!
  246.  */
  247.  
  248.  
  249. #define NG(nn)    &Gadgets[nn+1]
  250. #define G_YGLOB 1
  251. #define G_XGLOB 2
  252.  
  253. XPI Props[] = {
  254.     { AUTOKNOB|FREEVERT , 0, 0, 0x1FFF, 0x1FFF }
  255. };
  256.  
  257. IM Images[] = {
  258.     { 0,0,2,1,1, NULL, 1, 0, NULL },
  259. };
  260.  
  261. GADGET Gadgets[] = {
  262.     {
  263.     NULL, -15, 11, 15, -19, GADGIMAGE|GADGHCOMP|GRELRIGHT|GRELHEIGHT,
  264.     GADGIMMEDIATE|RIGHTBORDER|RELVERIFY,PROPGADGET,
  265.     (APTR)&Images[0],NULL,NULL,0,(APTR)&Props[0], G_YGLOB, 0
  266.     },
  267. };
  268.  
  269. GADGET *Gc;
  270. long GUx, GUy;
  271.  
  272. init_gadgets(nw, ppo)
  273. NW *nw;
  274. XPI **ppo;
  275. {
  276.     nw->FirstGadget = &Gadgets[0];
  277.     *ppo = &Props[0];
  278. }
  279.  
  280.  
  281.